# More info at http://psautodeploy.codeplex.com
# Author: SPFernando

Import-Module .\Utils.ps1
Import-Module .\Solutions.ps1
Import-Module .\Features.ps1

# Show Menu function
function ShowMenu {
	param(
		[parameter(Position=0, Mandatory=$true, HelpMessage="Enter your menu text")]
		[ValidateNotNullOrEmpty()]
		[string]$Menu,
		[parameter(Position=1, Mandatory=$true)]
		[ValidateNotNullOrEmpty()]
		[string]$Title="Menu",
		[switch]$ClearScreen
	)

	if ($ClearScreen) {
		Clear-Host
	}
		
	$MenuPrompt = $title 
	$MenuPrompt += "`n"	
	$MenuPrompt += "-" * $title.Length
	$MenuPrompt += "`n"	
	$MenuPrompt += $Menu

	Read-Host -Prompt $MenuPrompt
}

# Retrieve Path and Url
function GetPathUrl {
	param(
		[parameter(Position=0, Mandatory=$true)]
		[PSObject]$Info
	)

	$PathFalse = $true
	
	do {
		# File Path
		$Path = Read-Host "`nWSP path (Ej. C:\MyWSPsFolder\)" 
		
		# If Path ok
		if ($Path -and (Test-Path $Path) -eq $true) {
			
			# Getting files with *.WSP extension on Path			
			$Files = Get-ChildItem $Path | ?{$_.extension -eq ".wsp"} | Sort-Object Name
			
			if ($Files) {
				$Info | Add-Member -MemberType NoteProperty -Name "Path" -Value $Path -Force								
				$Info | Add-Member -MemberType NoteProperty -Name "Wsp" -Value $Files -Force
				$PathFalse = $false
			}
			else {
				# If File Path is Empty
				Write-Warning "`nDirectory path not include valid files." 
				LogWrite "WARNING - Path not include files with *.wsp extension"
				Start-Sleep -milliseconds 750
			}
		}
		else {
			# If File Path is not Valid
			Write-Warning "`nDirectory path is not valid, please, try insert with valid format (eg: 'C:\SharePoint2013\')" 
			LogWrite "WARNING - Path not valid. Returning client's control."
			Start-Sleep -milliseconds 750
		}
	} while($PathFalse)
	
	$SiteUrlFalse = $true
	
	do {
		$Url = Read-Host "`nSite Url (Ej. http://myHostName:1111)" 
		
		if ($Url) {
			# Get Site from Url
			$Site = Get-SPSite $Url
			
			if ($Site) {	
				# Url SPSite
				$Info | Add-Member -MemberType NoteProperty -Name "Site" -Value $Site -Force
				$Info | Add-Member -MemberType NoteProperty -Name "Url" -Value  $Url -Force
				$SiteUrlFalse = $false
			}
			else {
				# If Url Path is not Valid
				Write-Warning "`nSPSite url does not exists, if webapplication doesn't exists, please, contact with Farm administrator." 
				LogWrite "WARNING - Site url does not exists. Returning client's control."
				Start-Sleep -milliseconds 750
			}
		}
		else {
			# If Url is Empty
			Write-Warning "`nSPSite may not be null." 
			LogWrite "WARNING - Site not valid. Returning client's control."
			Start-Sleep -milliseconds 750
		}
	} while($SiteUrlFalse)		
}

# Report Operation
function Report {
	param (
		[parameter(Position=0, Mandatory=$false)]
		[Int]$Installed, 
		[parameter(Position=1, Mandatory=$false)]
		[Int]$Updated, 
		[parameter(Position=2, Mandatory=$true)]
		[bool]$Install
	)
	
	if ($Install) {	
		Write-Host "`nInstalled solutions: $Installed" -ForegroundColor "Yellow"
		Write-Host "`nUpdated solutions: $Updated" -ForegroundColor "Yellow"
		LogWrite "REPORT - Installed solutions: $Installed"
		LogWrite "REPORT - Updated solutions: $Updated"
	}
	else {
		Write-Host "`nRemoved solutions: $Installed" -ForegroundColor "Yellow"
		LogWrite "REPORT - Removed solutions: $Installed"
	}	
	Write-Host "`nOperation is done. Press any key for prompt menu." -ForegroundColor "DarkGreen"
	KeyDown	
}				

# Ready Execution
Clear-Host
LogWrite
LogWrite "TRACE - Initializing PS Auto Deploy"

$psHost = Get-Host
$psWindow = $psHost.UI.RawUI
$psWindow.WindowTitle = "PSAutoDeploy.exe"
$psWindow.ForegroundColor = "Gray"

# Buffer resize
$bufferSize = $psWindow.buffersize
$bufferSize.width = 70
$bufferSize.height = 70
$psWindow.buffersize = $bufferSize

# Window resize
$windowSize = $psWindow.windowsize
$windowSize.Height = 70
$windowSize.Width = 70
$psWindow.windowsize = $windowSize

# Window repositioning
$windowPos = $psWindow.windowposition
$windowPos.x = 0
$windowPos.y = 0
$psWindow.windowposition = $windowPos

LogWrite "TRACE - Internal cmd operations completed"

$Menu=@"
	1 Full Install
	2 Step-by-Step Install
	3 Uninstall Solutions
	4 IIS Reset
	Q Quit

Select a task by number or Q to quit
"@

Write-Host "`nWellcome to PS Auto Deploy. Press any key." 
KeyDown

LogWrite "TRACE - Activating PSSnapin"
Add-PSSnapin Microsoft.SharePoint.PowerShell

LogWrite "TRACE - Creating PSObject"
$Global:Info = New-Object PSObject
$NoExit = $true

do {
    switch (ShowMenu $Menu "PSAutoDeploy" -clear) {
		"1" {			
			Clear-Host
			LogWrite "TRACE - Auto install."
			GetPathUrl ($Info)		
			
			try {
				$ErrorActionPreference = 'Stop'

				# Counters
				$CounterInstall = 0
				$CounterUpdate = 0
			
				# Solutions in Farm
				$Solutions = (Get-SPFarm).Solutions | Foreach-Object {
					$SolutionNames += $_.name;
				}
							
				# For each *.WSP
				foreach ($Item in $Info.Wsp) {				
					ShowHeader $Item
										
					# If Solution exists inside Farm
					if ($SolutionNames -match $Item.ToString()) {
						# Update Solution
						UpdateSolution $Item.Fullname $Item.Name $Info.Url $true
						
						# Install Features inside Solution
						AddFeatures $Info.Site $Item.Name $true
						
						$CounterUpdate += 1
					}
					
					else {					
						# Install Solution
						AddSolution $Item.Fullname $Item.Name $Info.Url $true
						
						# Install Features inside Solution
						AddFeatures $Info.Site $Item.Name $true
						
						$CounterInstall += 1
					}
				}

				Report $CounterInstall $CounterUpdate $true						
			}
			catch {
				# Show Error
				Write-Error "`n$_.Exception.Message." 
				LogWrite "ERROR - $_.Exception.Message"
				KeyDown
			}
		}
		"2" {			
			Clear-Host
			LogWrite "TRACE - Step-by-step installing operation"
			GetPathUrl ($Info)		
			
			try {
				$ErrorActionPreference = 'Stop'

				# Counters
				$CounterInstall = 0
				$CounterUpdate = 0
			
				# Solutions in Farm
				$Solutions = (Get-SPFarm).Solutions | Foreach-Object{
					$SolutionNames += $_.name;
				}
							
				# For each *.WSP
				foreach ($Item in $Info.Wsp) {				
					ShowHeader $Item
										
					# If Solution exists inside Farm
					if ($SolutionNames -match $Item.ToString()) {						
						$SolutionUpdate = YesNo "Solution $Item exists" "Do you want update?"
						
						if ($SolutionUpdate) {
							# Update Solution
							UpdateSolution $Item.Fullname $Item.Name $Info.Url
							
							# Install Features inside Solution
							AddFeatures $Info.Site $Item.Name
							
							$CounterUpdate += 1
						}
					}
					
					else {					
						# Install Solution
						AddSolution $Item.Fullname $Item.Name $Info.Url
						
						# Install Features inside Solution
						AddFeatures $Info.Site $Item.Name
						
						$CounterInstall += 1
					}
				}

				Report $CounterInstall $CounterUpdate $true						
			}
			catch {
				# Show Error
				Write-Error "`n$_.Exception.Message." 
				LogWrite "ERROR - $_.Exception.Message"
				KeyDown
			}
		}
		
		"3" {
			LogWrite "TRACE - Remove existing solutions."
			if ((Get-SPFarm).Solutions.Count -gt 0) {
	
				Clear-Host
				GetPathUrl ($Info)		
				
				try {

					$ErrorActionPreference = 'Stop'

					# Counters
					$CounterUninstall = 0
				
					# Solutions in Farm
					$Solutions = (Get-SPFarm).Solutions | Foreach-Object{
						$SolutionNames += $_.name;
					}
								
					# For each *.WSP
					foreach ($Item in $Info.Wsp) {					
						# If Solution exists inside Farm
						if ($SolutionNames -match $Item.ToString()) {
							
							ShowHeader $Item
						
							# Remove Features inside Solution
							RemoveFeature $Info.Site $item.Name
							
							# Remove Solution
							UninstallSolution $Item.Name $Info.Url
							
							$CounterUninstall += 1
						}
						
						else {
							Write-Warning "`nSolution $Item not presents in the farm"
							KeyDown
						}
					}

					Report $CounterUninstall 0 $false						
				}
				catch {
					# Show Error
					Write-Error "`n$_.Exception.Message. Uninstall step was stopped." 
					LogWrite "ERROR - $_.Exception.Message"
					KeyDown
				}		
			}
			else {
				Write-Warning "`nThere are no solutions in the solution store."
				LogWrite "WARNING - Solution Store is empty"
				KeyDown
			}
		}
		
		"4" {
			Clear-Host
			Reset
		}
		
		"Q" {
			Write-Host "`nClosing application..." -ForegroundColor Cyan		
			LogWrite "TRACE - Closing application"
			Start-Sleep -milliseconds 750
			Clear-Host			
			$NoExit = $false
        }
		 
		default {
			Write-Warning "`nInvalid Choice. Try again."
			LogWrite "WARNING - Invalid choice menu option"
			Start-Sleep -milliseconds 750
		}
    }
} while ($NoExit)
# Reset Console Color
[console]::ResetColor()
LogWrite "TRACE - Log operation ended"

